package logic

import (
	"context"
	"fmt"
	"strconv"
	"strings"
	"time"

	"mall/common/enumx"
	"mall/common/modelx"
	"mall/common/moneyx"
	"mall/common/resultx"
	"mall/service/blog/model"
	"mall/service/blog/rpc/internal/svc"
	"mall/service/blog/rpc/types/blog"

	log "github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type BookDetailLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewBookDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BookDetailLogic {
	return &BookDetailLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *BookDetailLogic) BookDetail(in *blog.BookDetailReq) (*blog.BookDetailResp, error) {
	if in.Preload == "" && in.EagerLoad == "" {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	logx.Infof("BookDetailReq: %+v ", in)
	// Preload:\"blogTerm:Name,Slug,Name,Slug,Name,Slug;blogBook:CommentStatus,Date,Id,Uri,Title;blogMedia:altText,sourceUrl,mediaDetails;blogBookDetail:ContentHtml;blogBookRelation:Id,title,Slug,Uri,Link;blogBookMeta:fullHead,title,metaDesc\" EagerLoad:\"blogBook:blogTerm,blogMedia,blogBookDetail,blogBookRelation,blogTerm,blogBookMeta,blogTerm\" Filter:\"Id,equalTo:40046\" AsPreview:true "}
	// Id:40046 Preload:\"blogBookDetail:ContentHtml;blogMedia:altText,mediaDetails,Thumbnail,Url;blogBookRelation:brand,perfume,nose,group,note\" EagerLoad:\"blogBook:blogBookDetail,blogMedia,blogBookRelation\"
	// Id:40046  Preload:\"blogBookDetail:ContentHtml;blogMedia:altText,mediaDetails,Thumbnail,Url\"  EagerLoad:\"blogBook:blogBookDetail,blogMedia,blogTerm,blogBookRelation;blogBookRelation:brand\"

	preloadMap, eagerLoadMap := modelx.GetPreloadMap(in.Preload, in.EagerLoad)
	logx.Infof("preloadMap: %+v ", preloadMap)
	// preloadMap: map[blogBook:[Title Id Uri] blogBookDetail:[ContentHtml] blogBookMeta:[fullHead title metaDesc] blogMedia:[altText sourceUrl mediaDetails]]
	// preloadMap: map[blogBook:[] blogBookDetail:[ContentHtml] blogBookRelation:[] blogMedia:[altText mediaDetails Thumbnail Url] blogTerm:[] brand:[]]
	logx.Infof("eagerLoadMap: %+v ", eagerLoadMap)
	// eagerLoadMap: map[blogBook:[blogBookDetail blogMedia blogBookMeta blogBookMeta]]
	// eagerLoadMap: map[blogBook:[blogBookDetail blogMedia blogTerm blogBookRelation] blogBookRelation:[brand]]

	blogBookEntityName := model.RpcEntityNames.BlogBook
	_, hasSettingMap := model.RpcEntityPreloadMap[blogBookEntityName] // BlogBook的关联字段
	if !hasSettingMap {
		return &blog.BookDetailResp{}, nil
	}

	blogBookRepositoryName := model.RepositoryNames.BlogBook
	columnMap, hasColumnMap := model.RepositoryPreloadMap[blogBookRepositoryName] // BlogBook的数据库字段
	if !hasColumnMap {
		return &blog.BookDetailResp{}, nil
	}

	blogBookRelationEntityName := model.RpcEntityNames.BlogBookRelation
	blogBookRelationSettingMap, ok := model.RpcEntityPreloadMap[blogBookRelationEntityName]
	if !ok {
		return &blog.BookDetailResp{}, nil
	}

	sectionMap := make(map[uint64]string) // 记录 BlogBookRelation 的全部 section name
	for _, s := range blogBookRelationSettingMap {
		if s.Id > 0 {
			if _, exist := sectionMap[s.Id]; !exist {
				sectionMap[s.Id] = s.Name
			}
		}
	}

	// 解析 preload 的字段
	var selectCols []string
	if preloadFields, hasPreloadFields := preloadMap[blogBookEntityName]; hasPreloadFields {
		selectColMap := make(map[string]string)
		for _, field := range preloadFields {
			if _, exist := selectColMap[field]; !exist {
				if column, hasColumn := columnMap[field]; hasColumn {
					selectColMap[field] = column
				} else {
					selectColMap[field] = ""
				}
			}
		}
		for _, column := range selectColMap {
			if column != "" {
				selectCols = append(selectCols, column)
			}
		}
	}

	var entry *model.BlogKnowledgeBasis
	if in.Filter != "" {
		var filterMap map[string]map[string][]any
		filterMap = modelx.GetFilterMap(in.Filter, columnMap)
		logx.Infof("filterMap: %+v ", filterMap)
		// filterMap: map[guid:map[equalTo:[perfumes Acqua-di-Parma Blu-Mediterraneo-Arancia-di-Capri-1999]]]

		var asPreview string
		if in.AsPreview {
			asPreview = "1"
		}
		var pageSize int64 = 1
		entryList, _, err := l.svcCtx.BlogBook.GetList(l.ctx, model.M{
			"asPreview": asPreview,
			"pageSize":  pageSize,
			"select":    strings.Join(selectCols, ","),
		}, -1, filterMap)
		if err != nil {
			return nil, err
		}

		if len(entryList) == 0 {
			return &blog.BookDetailResp{}, nil
		}

		entry = entryList[0]
	} else if in.Id > 0 {
		entrySingle, err := l.svcCtx.BlogBook.FindOne(l.ctx, in.Id, selectCols)
		if err != nil {
			if err == model.ErrNotFound {
				return &blog.BookDetailResp{}, nil
			}

			return nil, err
		}

		entry = entrySingle
	}

	if entry == nil {
		return &blog.BookDetailResp{}, nil
	}
	eid := entry.ID

	var contentHtml string
	var media []*blog.BlogMedia
	var meta []*blog.BlogMeta
	var entries []*blog.BlogEntry
	subEntitySettingMap := make(map[string]map[string]*model.ColumnSetting)
	if eagerLoadEntities, hasEagerLoadEntities := eagerLoadMap[blogBookEntityName]; hasEagerLoadEntities {
		for _, entity := range eagerLoadEntities {
			if entitySettingMap, hasEntitySettingMap := model.RpcEntityPreloadMap[entity]; hasEntitySettingMap {
				subEntitySettingMap[entity] = entitySettingMap
			}
		}
	}

	blogBookDetailEntityName := model.RpcEntityNames.BlogBookDetail
	blogBookDetailRepositoryName := model.RepositoryNames.BlogBookDetail
	var simple bool = true
	if _, hasEntitySettingMap := subEntitySettingMap[blogBookDetailEntityName]; hasEntitySettingMap {
		simple = false
		subPreloadFields, hasSubPreloadFields := preloadMap[blogBookDetailEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[blogBookDetailRepositoryName]
		if hasSubPreloadFields && hasSubColumnMap {
			selectColMap := make(map[string]string)
			for _, field := range subPreloadFields {
				if _, exist := selectColMap[field]; !exist {
					if column, hasColumn := subColumnMap[field]; hasColumn {
						selectColMap[field] = column
					} else {
						selectColMap[field] = ""
					}
				}
			}
			var subSelectCols []string
			for _, column := range selectColMap {
				if column != "" {
					subSelectCols = append(subSelectCols, column)
				}
			}

			detailFilterMap := make(map[string]map[string][]any)
			detailFilterMap[model.BlogKnowledgeBaseDetailColumns.KnowledgeBaseID] = map[string][]any{
				"equalTo": []any{eid},
			}
			var pageSize int64 = 1
			detailList, _, listErr := l.svcCtx.BlogBook.GetDetail(l.ctx, model.M{
				"pageSize": pageSize,
				"select":   strings.Join(subSelectCols, ","),
			}, -1, detailFilterMap)
			if listErr != nil {
				return nil, listErr
			}

			if len(detailList) > 0 {
				contentHtml = detailList[0].PostContent
			}
		}
	}

	blogMediaEntityName := model.RpcEntityNames.BlogMedia
	blogMediaRepositoryName := model.RepositoryNames.BlogMedia
	var blogMediaSelectCols string
	if _, hasEntitySettingMap := subEntitySettingMap[blogMediaEntityName]; hasEntitySettingMap {
		subPreloadFields, hasSubPreloadFields := preloadMap[blogMediaEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[blogMediaRepositoryName]
		if hasSubPreloadFields && hasSubColumnMap {
			selectColMap := make(map[string]string)
			for _, field := range subPreloadFields {
				if _, exist := selectColMap[field]; !exist {
					if column, hasColumn := subColumnMap[field]; hasColumn {
						selectColMap[field] = column
					} else {
						selectColMap[field] = ""
					}
				}
			}
			var subSelectCols []string
			for _, column := range selectColMap {
				if column != "" {
					subSelectCols = append(subSelectCols, column)
				}
			}
			blogMediaSelectCols = strings.Join(subSelectCols, ",")

			mediaFilterMap := make(map[string]map[string][]any)
			mediaFilterMap[model.BlogAttachmentRelationshipColumns.ObjectID] = map[string][]any{
				"equalTo": []any{eid},
			}
			mediaFilterMap[model.BlogAttachmentRelationshipColumns.ObjectType] = map[string][]any{
				"equalTo": []any{enumx.PostTypeKnowledgeBase},
			}
			var pageSize int64
			if simple {
				mediaFilterMap[model.BlogAttachmentRelationshipColumns.AttachmentThumbnail] = map[string][]any{
					"equalTo": []any{1},
				}
				pageSize = 1
			}
			// todo: 不包含order字段则只获取一张，按缩略图和sorter排序
			mediaList, _, listErr := l.svcCtx.BlogBook.GetMedia(l.ctx, model.M{
				"pageSize": pageSize,
				"orderBy":  model.BlogAttachmentRelationshipColumns.AttachmentOrder,
				"select":   blogMediaSelectCols,
			}, -1, mediaFilterMap)
			if listErr != nil {
				return nil, listErr
			}

			if len(mediaList) > 0 {
				for _, item := range mediaList {
					media = append(media, &blog.BlogMedia{
						Uid:       int64(item.AttachmentRelationshipID),
						Id:        int64(item.AttachmentID),
						Uri:       item.AttachmentSource,
						Thumbnail: int32(item.AttachmentThumbnail),
						Order:     int32(item.AttachmentOrder),
						Url:       item.AttachmentImageURL,
						AltText:   item.AttachmentImageAlt,
						Meta:      item.AttachmentImageMeta,
					})
				}
			}
		}
	}

	blogPhotoEntityName := model.RpcEntityNames.BlogPhoto
	if _, hasEntitySettingMap := subEntitySettingMap[blogPhotoEntityName]; hasEntitySettingMap {
		subPreloadFields, hasSubPreloadFields := preloadMap[blogMediaEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[blogMediaRepositoryName]
		if hasSubPreloadFields && hasSubColumnMap {
			selectColMap := make(map[string]string)
			for _, field := range subPreloadFields {
				if _, exist := selectColMap[field]; !exist {
					if column, hasColumn := subColumnMap[field]; hasColumn {
						selectColMap[field] = column
					} else {
						selectColMap[field] = ""
					}
				}
			}
			var subSelectCols []string
			for _, column := range selectColMap {
				if column != "" {
					subSelectCols = append(subSelectCols, column)
				}
			}
			mediaFilterMap := make(map[string]map[string][]any)
			mediaFilterMap[model.BlogAttachmentRelationshipColumns.ObjectID] = map[string][]any{
				"equalTo": []any{eid},
			}
			mediaFilterMap[model.BlogAttachmentRelationshipColumns.ObjectType] = map[string][]any{
				"equalTo": []any{enumx.PostTypeKnowledgeBaseComplement},
			}
			mediaList, _, listErr := l.svcCtx.BlogBook.GetMedia(l.ctx, model.M{
				"orderBy": model.BlogAttachmentRelationshipColumns.AttachmentImageAlt,
				"select":  strings.Join(subSelectCols, ","),
			}, -1, mediaFilterMap)
			if listErr != nil {
				return nil, listErr
			}

			if len(mediaList) > 0 {
				for _, item := range mediaList {
					media = append(media, &blog.BlogMedia{
						Uid:       int64(item.AttachmentRelationshipID),
						Id:        int64(item.AttachmentID),
						Uri:       item.AttachmentSource,
						Thumbnail: int32(item.AttachmentThumbnail),
						Order:     int32(item.AttachmentOrder),
						Url:       item.AttachmentImageURL,
						AltText:   item.AttachmentImageAlt,
						Meta:      item.AttachmentImageMeta,
					})
				}
			}
		}
	}

	blogBookMetaEntityName := model.RpcEntityNames.BlogBookMeta
	var blogBookMetaKeys []any
	blogBookMetaKeyMap := make(map[string]string)
	if entitySettingMap, hasEntitySettingMap := subEntitySettingMap[blogBookMetaEntityName]; hasEntitySettingMap {
		if subPreloadFields, hasSubPreloadFields := preloadMap[blogBookMetaEntityName]; hasSubPreloadFields {
			for _, field := range subPreloadFields {
				fieldSetting, hasFieldSetting := entitySettingMap[field]
				if hasFieldSetting && fieldSetting.Name != "" {
					blogBookMetaKeys = append(blogBookMetaKeys, fieldSetting.Name)
					blogBookMetaKeyMap[fieldSetting.Name] = field
				}
			}
			if len(blogBookMetaKeys) > 0 {
				metaFilterMap := make(map[string]map[string][]any)
				metaFilterMap[model.BlogKnowledgeBaseMetumColumns.KnowledgeBaseID] = map[string][]any{
					"equalTo": []any{eid},
				}
				metaFilterMap[model.BlogKnowledgeBaseMetumColumns.MetaKey] = map[string][]any{
					"in": blogBookMetaKeys,
				}
				metaList, _, listErr := l.svcCtx.BlogBook.GetMeta(l.ctx, model.M{}, -1, metaFilterMap)
				if listErr != nil {
					return nil, listErr
				}

				if len(metaList) > 0 {
					for _, metum := range metaList {
						if metum.MetaKey != "" && metum.MetaValue.Valid {
							if field, hasField := blogBookMetaKeyMap[metum.MetaKey]; hasField {
								meta = append(meta, &blog.BlogMeta{
									Id:    int64(metum.MetaID),
									Key:   field,
									Value: metum.MetaValue.String,
								})
							}
						}
					}
				}
			}
		}
	}

	var categories []*blog.BlogCategory
	var tags []*blog.BlogTag
	var sections []*blog.BlogCategory
	var termId uint64
	blogTermEntityName := model.RpcEntityNames.BlogTerm
	blogTermRepositoryName := model.RepositoryNames.BlogTerm
	if _, hasEntitySettingMap := subEntitySettingMap[blogTermEntityName]; hasEntitySettingMap {
		subPreloadFields, hasSubPreloadFields := preloadMap[blogTermEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[blogTermRepositoryName]
		if hasSubPreloadFields && hasSubColumnMap {
			subFilterMap := make(map[string]map[string][]any)
			subFilterMap[model.BlogTermRelationshipColumns.ObjectID] = map[string][]any{
				"equalTo": []any{eid},
			}
			subFilterMap[model.BlogTermRelationshipColumns.ObjectType] = map[string][]any{
				"equalTo": []any{enumx.PostTypeKnowledgeBase},
			}
			relationshipList, _, listErr := l.svcCtx.BlogTerm.GetRelationshipList(l.ctx, model.M{
				"select": model.BlogTermRelationshipColumns.TermID,
			}, -1, subFilterMap)
			if listErr != nil {
				return nil, listErr
			}

			if len(relationshipList) > 0 { // 有分类、标签、章节
				selectColMap := make(map[string]string)
				for _, field := range subPreloadFields {
					if _, exist := selectColMap[field]; !exist {
						if column, hasColumn := subColumnMap[field]; hasColumn {
							selectColMap[field] = column
						} else {
							selectColMap[field] = ""
						}
					}
				}
				var subSelectCols []string
				for _, column := range selectColMap {
					if column != "" {
						subSelectCols = append(subSelectCols, column)
					}
				}
				subSelectCols = append(subSelectCols, model.BlogTermColumns.ParentID)

				var tids []any // []model.BlogTerm.TermID
				for _, relationship := range relationshipList {
					tids = append(tids, relationship.TermID)
				}

				termFilterMap := make(map[string]map[string][]any)
				termFilterMap[model.BlogTermColumns.TermID] = map[string][]any{
					"in": tids,
				}
				termList, _, listErr := l.svcCtx.BlogTerm.GetList(l.ctx, model.M{
					"select": strings.Join(subSelectCols, ","),
				}, -1, termFilterMap)
				if listErr != nil {
					return nil, listErr
				}

				if len(termList) > 0 {
					var parentId int64
					for _, term := range termList {
						switch enumx.TermTaxonomy(term.Taxonomy) {
						case enumx.TermTaxonomyCategory: // 是分类
							categories = append(categories, &blog.BlogCategory{
								Id:   int64(term.TermID),
								Name: term.Name,
								Slug: term.Slug,
							})
						case enumx.TermTaxonomyTag: // 是标签
							tags = append(tags, &blog.BlogTag{
								Id:   int64(term.TermID),
								Name: term.Name,
								Slug: term.Slug,
							})
						case enumx.TermTaxonomyKnowledgeBase: // 是章节
							if termId > 0 { // 仅取一个
								continue
							}

							termId = term.TermID
							parentId = int64(term.ParentID)
							var alias string
							if s, ok := sectionMap[termId]; ok {
								alias = s
							}
							sections = append(sections, &blog.BlogCategory{
								Id:       int64(termId),
								Name:     term.Name,
								Slug:     term.Slug,
								Uri:      alias,
								ParentId: parentId,
							})
						}
					}

					for parentId > 0 {
						term, err := l.svcCtx.BlogTerm.FindOne(l.ctx, parentId, subSelectCols)
						if err != nil {
							if err == model.ErrNotFound {
								break
								parentId = 0
							}

							return nil, err
						}

						parentId = int64(term.ParentID)
						var alias string
						if s, ok := sectionMap[term.TermID]; ok {
							alias = s
						}
						sections = append(sections, &blog.BlogCategory{
							Id:       int64(term.TermID),
							Name:     term.Name,
							Slug:     term.Slug,
							Uri:      alias,
							ParentId: parentId,
						})
					}
				}
			}
		}
	}

	blogBookRelationRepositoryName := model.RepositoryNames.BlogBookRelation
	if entitySettingMap, ok := subEntitySettingMap[blogBookRelationEntityName]; ok {
		subPreloadFields, hasSubPreloadFields := preloadMap[blogBookRelationEntityName]
		subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[blogBookRelationRepositoryName]
		if hasSubPreloadFields && hasSubColumnMap {
			preloadMap := make(map[string]int)
			selectColMap := make(map[string]string)
			for idx, field := range subPreloadFields {
				if _, exist := preloadMap[field]; !exist {
					preloadMap[field] = idx
					if column, hasColumn := subColumnMap[field]; hasColumn {
						selectColMap[field] = column
					} else {
						selectColMap[field] = ""
					}
				}
			}

			var relationIds []any
			for _, s := range blogBookRelationSettingMap {
				if s.Id > 0 {
					if _, exist := preloadMap[s.Name]; exist {
						relationIds = append(relationIds, s.Id)
					}
				}
			}

			if len(relationIds) > 0 {
				var bothWay bool
				for _, s := range entitySettingMap {
					if s.Id == termId {
						bothWay = s.BothWay
						break
					}
				}
				var subSelectCols []string
				for _, column := range selectColMap {
					if column != "" {
						subSelectCols = append(subSelectCols, column)
					}
				}

				var relationList []*model.BlogKnowledgeBaseRelationship
				var listErr error
				var tids []any
				tidMap := make(map[uint64]int) // Map: model.BlogKnowledgeBasis.ID => int
				if bothWay {                   // 先正向，比如关联时：香水 => 品牌，查询时，品牌 => 香水
					relationFilterMap := make(map[string]map[string][]any)
					relationFilterMap[model.BlogKnowledgeBaseRelationshipColumns.FromEntryID] = map[string][]any{
						"equalTo": []any{eid},
					}
					relationFilterMap[model.BlogKnowledgeBaseRelationshipColumns.ToSectionID] = map[string][]any{
						"in": relationIds,
					}
					relationSelectCols := []string{
						model.BlogKnowledgeBaseRelationshipColumns.ToEntryID,
						model.BlogKnowledgeBaseRelationshipColumns.ToSectionID,
						model.BlogKnowledgeBaseRelationshipColumns.ToEntryGroup,
						model.BlogKnowledgeBaseRelationshipColumns.ToEntryOrder,
						model.BlogKnowledgeBaseRelationshipColumns.ToEntryMeta,
					}
					relationList, _, listErr = l.svcCtx.BlogBook.GetRelationshipList(l.ctx, model.M{
						"select":  strings.Join(relationSelectCols, ","),
						"orderBy": model.BlogKnowledgeBaseRelationshipColumns.ToEntryOrder,
					}, -1, relationFilterMap)
					if listErr != nil {
						return nil, listErr
					}

					if len(relationList) > 0 {
						for i, relation := range relationList {
							if _, exist := tidMap[relation.ToEntryID]; !exist {
								tidMap[relation.ToEntryID] = i
								tids = append(tids, relation.ToEntryID)
							}
						}
					}
				}

				// 再反向
				reverseFilterMap := make(map[string]map[string][]any)
				reverseFilterMap[model.BlogKnowledgeBaseRelationshipColumns.ToEntryID] = map[string][]any{
					"equalTo": []any{eid},
				}
				reverseFilterMap[model.BlogKnowledgeBaseRelationshipColumns.FromSectionID] = map[string][]any{
					"in": relationIds,
				}
				reverseSelectCols := []string{
					model.BlogKnowledgeBaseRelationshipColumns.FromEntryID,
					model.BlogKnowledgeBaseRelationshipColumns.FromSectionID,
					model.BlogKnowledgeBaseRelationshipColumns.ToEntryGroup,
					model.BlogKnowledgeBaseRelationshipColumns.ToEntryOrder,
					model.BlogKnowledgeBaseRelationshipColumns.ToEntryMeta,
				}
				reverseList, _, listErr := l.svcCtx.BlogBook.GetRelationshipList(l.ctx, model.M{
					"select":  strings.Join(reverseSelectCols, ","),
					"orderBy": model.BlogKnowledgeBaseRelationshipColumns.EntryRelationshipID,
				}, -1, reverseFilterMap)
				if listErr != nil {
					return nil, listErr
				}

				if len(reverseList) > 0 {
					for i, relation := range reverseList {
						if _, exist := tidMap[relation.FromEntryID]; !exist {
							tidMap[relation.FromEntryID] = i
							tids = append(tids, relation.FromEntryID)
						}
					}
				}

				entryMap := make(map[uint64]*model.BlogKnowledgeBasis)
				mediaMap := make(map[uint64]*model.BlogAttachmentRelationship)
				metaMap := make(map[uint64][]*blog.BlogMeta)
				if len(tids) > 0 {
					entryFilterMap := make(map[string]map[string][]any)
					entryFilterMap[model.BlogKnowledgeBasisColumns.ID] = map[string][]any{
						"in": tids,
					}
					entryFilterMap[model.BlogKnowledgeBasisColumns.PostStatus] = map[string][]any{
						"equalTo": []any{enumx.PostStatusPublish},
					}
					var entrySelectCols []string
					if len(subSelectCols) > 0 {
						entrySelectCols = subSelectCols[:]
					} else {
						entrySelectCols = []string{
							model.BlogKnowledgeBasisColumns.ID,
							model.BlogKnowledgeBasisColumns.PostTitle,
							model.BlogKnowledgeBasisColumns.PostName,
							model.BlogKnowledgeBasisColumns.PostExcerpt,
							model.BlogKnowledgeBasisColumns.GUID,
						}
					}
					entryList, _, listErr := l.svcCtx.BlogBook.GetList(l.ctx, model.M{
						"select": strings.Join(entrySelectCols, ","),
					}, -1, entryFilterMap)
					if listErr != nil {
						return nil, listErr
					}

					if len(entryList) > 0 {
						var eids []any
						for _, e := range entryList {
							entryMap[e.ID] = e
							eids = append(eids, e.ID)
						}

						subFilterMap := make(map[string]map[string][]any)
						subFilterMap[model.BlogAttachmentRelationshipColumns.ObjectID] = map[string][]any{
							"in": eids,
						}
						subFilterMap[model.BlogAttachmentRelationshipColumns.ObjectType] = map[string][]any{
							"equalTo": []any{enumx.PostTypeKnowledgeBase},
						}
						subFilterMap[model.BlogAttachmentRelationshipColumns.AttachmentThumbnail] = map[string][]any{
							"equalTo": []any{1},
						}
						mediaList, _, listErr := l.svcCtx.BlogBook.GetMedia(l.ctx, model.M{
							"select": blogMediaSelectCols,
						}, -1, subFilterMap)
						if listErr != nil {
							return nil, listErr
						}

						if len(mediaList) > 0 {
							for _, mediaItem := range mediaList {
								if _, exist := mediaMap[mediaItem.ObjectID]; !exist {
									mediaMap[mediaItem.ObjectID] = mediaItem
								}
							}
						}

						if len(blogBookMetaKeys) > 0 {
							subMetaFilterMap := make(map[string]map[string][]any)
							subMetaFilterMap[model.BlogKnowledgeBaseMetumColumns.KnowledgeBaseID] = map[string][]any{
								"in": eids,
							}
							subMetaFilterMap[model.BlogKnowledgeBaseMetumColumns.MetaKey] = map[string][]any{
								"in": blogBookMetaKeys,
							}
							metaList, _, listErr := l.svcCtx.BlogBook.GetMeta(l.ctx, model.M{}, -1, subMetaFilterMap)
							if listErr != nil {
								return nil, listErr
							}

							if len(metaList) > 0 {
								for _, metum := range metaList {
									if metum.MetaKey != "" && metum.MetaValue.Valid {
										if field, hasField := blogBookMetaKeyMap[metum.MetaKey]; hasField {
											metaMap[metum.KnowledgeBaseID] = append(metaMap[metum.KnowledgeBaseID], &blog.BlogMeta{
												Id:    int64(metum.MetaID),
												Key:   field,
												Value: metum.MetaValue.String,
											})
										}
									}
								}
							}
						}
					}

					if len(relationList) > 0 {
						for _, relation := range relationList {
							if _, exist := tidMap[relation.ToEntryID]; !exist {
								continue
							}

							if e, exist := entryMap[relation.ToEntryID]; exist {
								var section string
								if s, ok := sectionMap[relation.ToSectionID]; ok {
									section = s
								}
								var url string
								if a, ok := mediaMap[relation.ToEntryID]; ok {
									url = a.AttachmentImageURL
								}
								var year string
								var averageRating string
								if ms, ok := metaMap[relation.ToEntryID]; ok {
									if len(ms) > 0 {
										for _, m := range ms {
											switch m.Key {
											case "year":
												year = m.Value
											case "averageRating":
												if f, err := strconv.ParseFloat(m.Value, 64); err == nil {
													averageRating = moneyx.FormatStar(f, 1)
												} else {
													log.Info(fmt.Sprintf("BookDetail averageRating err: %+v", err))
												}
											}
										}
									}
								}

								entries = append(entries, &blog.BlogEntry{
									Id:            int64(e.ID),
									Title:         e.PostTitle,
									Slug:          e.PostName,
									Excerpt:       e.PostExcerpt,
									Url:           url,
									Link:          e.GUID,
									SectionId:     int64(relation.ToSectionID),
									Section:       section,
									GroupId:       int64(relation.ToEntryGroup),
									Order:         int64(relation.ToEntryOrder),
									Year:          year,
									AverageRating: averageRating,
								})
							}
						}
					}
					if len(reverseList) > 0 {
						for _, reverse := range reverseList {
							if _, exist := tidMap[reverse.FromEntryID]; !exist {
								continue
							}

							if e, exist := entryMap[reverse.FromEntryID]; exist {
								var section string
								if s, ok := sectionMap[reverse.FromSectionID]; ok {
									section = s
								}
								var url string
								if a, ok := mediaMap[reverse.FromEntryID]; ok {
									url = a.AttachmentImageURL
								}
								var year string
								var averageRating string
								if ms, ok := metaMap[reverse.FromEntryID]; ok {
									if len(ms) > 0 {
										for _, m := range ms {
											switch m.Key {
											case "year":
												year = m.Value
											case "averageRating":
												if f, err := strconv.ParseFloat(m.Value, 64); err == nil {
													averageRating = moneyx.FormatStar(f, 1)
												} else {
													log.Info(fmt.Sprintf("BookDetail averageRating err: %+v", err))
												}
											}
										}
									}
								}

								entries = append(entries, &blog.BlogEntry{
									Id:            int64(e.ID),
									Title:         e.PostTitle,
									Slug:          e.PostName,
									Url:           url,
									Link:          e.GUID,
									SectionId:     int64(reverse.FromSectionID),
									Section:       section,
									GroupId:       int64(reverse.ToEntryGroup),
									Order:         int64(reverse.ToEntryOrder),
									Year:          year,
									AverageRating: averageRating,
								})
							}
						}
					}
				}
			}
		}
	}

	if !simple && eid > 0 && in.VisitorId > 0 && in.PlatformId > 0 && in.SearchLogId >= 0 {
		l.svcCtx.BlogUser.InsertClickLog(l.ctx, &model.BlogUserClickLog{
			UserID:      uint64(in.VisitorId),
			PlatformID:  uint(in.PlatformId),
			SearchLogID: uint64(in.SearchLogId),
			ObjectID:    eid,
			ObjectType:  uint16(enumx.PostTypeKnowledgeBase),
			SectionID:   uint64(termId),
			CreatedAt:   time.Now(),
		})
	}

	return &blog.BookDetailResp{
		Id:            int64(eid),
		ParentId:      int64(entry.PostParentID),
		Title:         entry.PostTitle,
		Excerpt:       entry.PostExcerpt,
		Status:        int32(entry.PostStatus),
		CommentStatus: int32(entry.CommentStatus),
		Slug:          entry.PostName,
		Uri:           entry.GUID,
		Date:          modelx.FormatTime(entry.PostDate, ""),
		DateGmt:       modelx.FormatTime(entry.PostDateGMT, ""),
		Modified:      modelx.FormatTime(entry.PostModifiedDate, ""),
		ModifiedGmt:   modelx.FormatTime(entry.PostModifiedGMT, ""),
		Order:         int64(entry.MenuOrder),
		CommentCount:  int32(entry.CommentCount),
		ContentHtml:   contentHtml,
		Categories:    categories,
		Tags:          tags,
		Sections:      sections,
		Media:         media,
		Meta:          meta,
		Relations:     entries,
	}, nil
}
